package com.study.project.adapter;

import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.study.project.config.http.HttpComponent;
import com.study.project.config.kafka.KafkaTopic;
import com.study.project.config.redis.RedisLockUtil;
import com.study.project.service.MessageQueueService;
import com.study.project.service.RedisCacheService;

import lombok.extern.slf4j.Slf4j;

/**
 * @program: studyProject
 * @description:
 * @author: yangjie
 * @create: 2024-04-13 13:56
 **/
@Slf4j
@RestController
@RequestMapping(value = "/test")
public class TestController {

    @Resource
    private HttpComponent httpComponent;
    @Resource
    private RedisCacheService redisCacheService;
    @Resource
    private MessageQueueService messageQueueService;
    @Resource
    private RedisLockUtil redisLockUtil;
    @Resource
    private DefaultRedisScript<Long> counterRedisScript;
    @Resource
    private RedisTemplate<String, Long> redisTemplate;

    @GetMapping(value = "/cache")
    public Object getCache() {
        String key = "name";
        redisCacheService.limitRate(key, 10, TimeUnit.SECONDS);

        return redisCacheService.getCacheByKey(key);
    }

    private int times = 1;

    @Retryable(value = Exception.class, backoff = @Backoff(value = 100, multiplier = 1.5))
    @GetMapping(value = "/retry")
    public String retry(int number) {
        log.info("入口" + times++);
        if (number > 1) {
            throw new RuntimeException("错误");
        }
        log.info("调用了" + times++);
        return "重试";
    }

    @Recover
    public String doRecover(Exception exception, int number) {
        log.info("重试失败" + exception);
        return "重试";
    }

    @GetMapping(value = "/getUrlResult")
    public String getUrlResult(String url) {
        String content = httpComponent.getUrl(url);
        long currentTimeMillis = System.currentTimeMillis();
        if (currentTimeMillis % 2 == 0) {
            throw new RuntimeException("错误");
        }
        log.info("调用了" + times++);
        return content;
    }

    @GetMapping(value = "/count")
    public Integer count(Integer countTimes) {
        forCount(countTimes);
        return countTimes;
    }

    private void forCount(Integer countTimes) {
        for (int i = 0; i < countTimes; i++) {
            String countKey = "lua_redis_count_key";
            Integer maxCount = 5;
            Integer expireTimeSeconds = 5;
            Long result = redisTemplate.execute(counterRedisScript, Collections.singletonList(countKey), maxCount,
                expireTimeSeconds);
            System.out.println(result);
        }
    }

    @GetMapping(value = "/testLock")
    public void lockMessage(@RequestParam("message") String message) {
        for (int i = 0; i < 10; i++) {
            sendMessage(message);
        }
    }

    private void sendMessage(String message) {
        String lockKey = "lock_test_" + message + UUID.randomUUID();
        boolean success = redisLockUtil.lock(lockKey, 10, 6, TimeUnit.SECONDS);
        try {
            if (success) {
                messageQueueService.sendMessage(KafkaTopic.TEST, message);
            }
        } finally {
            redisLockUtil.unLock(lockKey);
        }
    }
}